/*
 * OPIAM Suite
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package opiam.admin.faare.unittests.service.services.trombinoscope;

import opiam.admin.faare.PropertiesManager;
import opiam.admin.faare.SearchResult;
import opiam.admin.faare.exception.ServiceException;
import opiam.admin.faare.service.UserContext;
import opiam.admin.faare.service.javabeans.Criteria;
import opiam.admin.faare.service.javabeans.SearchArgument;
import opiam.admin.faare.service.services.StandardService;
import opiam.admin.faare.service.services.trombinoscope.TrombinoscopeGenerator;
import opiam.admin.faare.unittests.TestResult;
import opiam.admin.faare.unittests.TestUtils;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.apache.log4j.Logger;

import java.io.ByteArrayOutputStream;

import java.util.ArrayList;
import java.util.List;


/**
 * TrombinoscopeGenerator class Test.
 */
public class TrombinoscopeGeneratorTest extends TestCase
{
    /** Instance of logger. */
    private static Logger _logger = Logger.getLogger(TrombinoscopeGeneratorTest.class);

    /** Test administrator DN. */
    private static final String DN_ADMIN = "uid=hmiller,ou=People,dc=mycompany,dc=com";

    /** Test administrator login. */
    private static final String LOGIN_ADMIN = "hmiller";

    /** Test administrator password. */
    private static final String PASSWORD_ADMIN = "hillock";

    /** Admin context. */
    private static UserContext _ADMINCONTEXT = new UserContext();

    /** Instance of the trace class. */
    private static TestUtils _test = new TestUtils(_logger);

    /** Set of attributes. */
    private static String[] attrsList = {"nomPrenom", "titre"};

    /** JPG image type. */
    private static final String JPG_IMAGE_TYPE = "jpg";

    /** GIF image type. */
    private static final String GIF_IMAGE_TYPE = "gif";

    /** PNG image type. */
    private static final String PNG_IMAGE_TYPE = "png";

    /** Image file name. */
    private static final String IMAGE_NAME = "artmengo.";

    /** Image file path. */
    private static final String IMAGE_PATH = "opiam.admin/faare/unittests/data/";

    /** PDF file name. */
    private static final String PDF_NAME = "artmengo.pdf";

    /** PDF 2 file name. */
    private static final String PDF_NAME2 = "pdftrombi2.pdf";

    /** PDF 3 file name. */
    private static final String PDF_NAME3 = "pdftrombi3.pdf";


    /** PDF file path. */
    private static final String PDF_PATH = "opiam.admin/faare/unittests/data/";

    /**
     * Creates a new TrombinoscopeGeneratorTest object.
     *
     * @param param  Parameter.
     */
    public TrombinoscopeGeneratorTest(String param)
    {
        super(param);

        try
        {
            PropertiesManager.getInstance();

            if (!_ADMINCONTEXT.isLoggedIn())
            {
                StandardService.logon(LOGIN_ADMIN, PASSWORD_ADMIN, _ADMINCONTEXT);
            }
        }
        catch (Exception e)
        {
            StringBuffer msg = new StringBuffer();
            msg.append("TrombinoscopeGeneratorTest constructor error");
            msg.append(TestUtils.NEXT);
            msg.append(e.toString());
            _test.displayResultError(msg.toString());
        }
    }

    /**
     * Method of the tests suite.
     *
     * @return Tests result.
     */
    public static Test suite()
    {
        TestSuite suite = new TestSuite();

        suite.addTest(new TrombinoscopeGeneratorTest("testBegin"));

        // TESTS SET
        suite.addTest(new TrombinoscopeGeneratorTest(
                "testGeneratePdfTrombinoscope"));
        suite.addTest(new TrombinoscopeGeneratorTest(
                "testGenerateTrombinoscope"));
        suite.addTest(new TrombinoscopeGeneratorTest(
                "testGeneratePdfTrombinoscopeError"));

        suite.addTest(new TrombinoscopeGeneratorTest("testEnd"));

        return (suite);
    }

    /**
     * Main method of the test class.
     *
     * @param args  Sets of the parameters.
     */
    public static void main(String[] args)
    {
        junit.textui.TestRunner.run(suite());
    }

    /**
     * Method to indicate the beginning of the class test.
     *
     */
    public static void testBegin()
    {
        TestResult.getInstance().setInitiator("TrombinoscopeGeneratorTest");

        _test.displayHeaderClass("TrombinoscopeGeneratorTest");
        assertTrue(true);
    }

    /**
     * Method to indicate the end of the class test.
     *
     */
    public static void testEnd()
    {
        _test.displayFooterClass(null);
        assertTrue(true);
        _test.displayTestStatement("TrombinoscopeGeneratorTest");
    }

    /**
     * Tests the Pdf trombinoscope creation.
     */
    public static void testGeneratePdfTrombinoscope()
    {
        _test.displayHeaderMethod("testGeneratePdfTrombinoscope");

        try
        {
            // Gets the entries list
            Criteria c1 = Criteria.getAndInstance();
            c1.addBeginsWith("id", "b");
            c1.addExists("photo");

            SearchArgument arg = new SearchArgument(c1,
                    _ADMINCONTEXT.findJBRessourceByName("person"), _ADMINCONTEXT);

            List args = new ArrayList();
            args.add(arg);

            SearchResult begEntries = StandardService.search(args, _ADMINCONTEXT);

            if (begEntries != null)
            {
                List entries = begEntries.getLResults();

                if (entries.size() > 0)
                {
                    // Gets the attributes list
                    ArrayList attrs = new ArrayList();

                    for (int i = 0; i < attrsList.length; i++)
                    {
                        attrs.add(attrsList[i]);
                    }

                    // generates a trombinoscope with 2 columns, and 6 entries,*
                    // and the first result of the search is not included.
                    ByteArrayOutputStream baos = TrombinoscopeGenerator.generatePdfTrombinoscope(1,
                            2, 6, entries, attrs);

                    if (baos != null)
                    {
                        // allows to create the reference pdf file for the following tests.
                        //_test.createFile(PDF_NAME, PDF_PATH, baos.toByteArray());
                        //_test.displayMsg("Number of entries : " + entries.size());
                        //_test.displayMsg("First entries : " + ((JBTop)entries.get(0)).getDn());
                        // Gets the reference pdf file.
                        byte[] refPdf = _test.readBytesFromFile(PDF_NAME,
                                PDF_PATH);
                        _test.displayMsg("Size of the generated PDF : " +
                            baos.size());
                        _test.displayMsg("Size of the reference PDF : " +
                            refPdf.length);

                        if (baos.size() == refPdf.length)
                        {
                            _test.displayResultSuccess(null);
                        }
                        else
                        {
                            _test.displayResultFailure(null);
                        }
                    }
                    else
                    {
                        _test.displayResultFailure("No trombinoscope generated");
                    }
                }
                else
                {
                    _test.displayResultFailure("No entries");
                }
            }
            else
            {
                _test.displayResultFailure("SearchResult = null");
            }
        }
        catch (Exception ex)
        {
            StringBuffer msg = new StringBuffer();
            msg.append("Exception : ");
            msg.append(TestUtils.NEXT);
            msg.append(ex.toString());
            _test.displayResultError(msg.toString());
        }

        _test.displayFooterMethod("testGeneratePdfTrombinoscope");
    }

    /**
     * Tests the graphical Trombinoscope creation.
     */
    public static void testGenerateTrombinoscope()
    {
        _test.displayHeaderMethod("testGenerateTrombinoscope");

        try
        {
            // Gets the entries list
            Criteria c1 = Criteria.getAndInstance();
            c1.addBeginsWith("id", "b");
            c1.addExists("photo");

            SearchArgument arg = new SearchArgument(c1,
                    _ADMINCONTEXT.findJBRessourceByName("person"), _ADMINCONTEXT);
            List args = new ArrayList();
            args.add(arg);

            SearchResult begEntries = StandardService.search(args, _ADMINCONTEXT);

            if (begEntries != null)
            {
                List entries = begEntries.getLResults();

                if (entries.size() > 0)
                {
                    // Gets the attributes list
                    ArrayList attrs = new ArrayList();

                    for (int i = 0; i < attrsList.length; i++)
                    {
                        attrs.add(attrsList[i]);
                    }

                    // generates a trombinoscope with 2 columns, and 6 entries,*
                    // and the first result of the search is not included.
                    // JPG trombi
                    testImageTromb(1, 2, 6, entries, attrs, JPG_IMAGE_TYPE);

                    // GIF trombi
                    testImageTromb(1, 2, 6, entries, attrs, GIF_IMAGE_TYPE);

                    // PNG trombi
                    testImageTromb(1, 2, 6, entries, attrs, PNG_IMAGE_TYPE);
                }
                else
                {
                    _test.displayResultFailure("No entries");
                }
            }
            else
            {
                _test.displayResultFailure("SearchResult = null");
            }
        }
        catch (Exception ex)
        {
            StringBuffer msg = new StringBuffer();
            msg.append("Exception : ");
            msg.append(TestUtils.NEXT);
            msg.append(ex.toString());
            _test.displayResultError(msg.toString());
        }

        _test.displayFooterMethod("testGenerateTrombinoscope");
    }

    /**
     * Tests the Pdf trombinoscope creation with error.
     */
    public static void testGeneratePdfTrombinoscopeError()
    {
        _test.displayHeaderMethod("testGeneratePdfTrombinoscopeError");

        try
        {
            // Gets the entries list
            Criteria c1 = Criteria.getAndInstance();
            c1.addBeginsWith("id", "b");
            c1.addExists("photo");

            SearchArgument arg = new SearchArgument(c1,
                    _ADMINCONTEXT.findJBRessourceByName("person"), _ADMINCONTEXT);

            List args = new ArrayList();
            args.add(arg);

            SearchResult begEntries = StandardService.search(args, _ADMINCONTEXT);

            if (begEntries != null)
            {
                List entries = begEntries.getLResults();

                if (entries.size() > 0)
                {
                    // Gets the attributes list
                    ArrayList attrs = new ArrayList();

                    for (int i = 0; i < attrsList.length; i++)
                    {
                        attrs.add(attrsList[i]);
                    }

                    // generates a trombinoscope with 2 columns, and 6 entries,*
                    // and the first result of the search is not included.
                    // result : 8 entries, 2 columns
                    ByteArrayOutputStream baos = null;

                    _test.displayMsg("Number of entries : " + entries.size());

                    _test.displayMsg(TestUtils.NEXT +
                        "Parameters = StartIndex : -1, NbColumns : 2, NbEntries : 6");

                    try
                    {
                        baos = TrombinoscopeGenerator.generatePdfTrombinoscope(-1,
                                2, 6, entries, attrs);
                        testPdfTromb(baos);
                    }
                    catch (ServiceException serex)
                    {
                        _test.displayResultSuccess("Error handled");
                    }
                    catch (Exception ex)
                    {
                        _test.displayResultFailure(ex.toString());
                    }

                    _test.displayMsg(TestUtils.NEXT +
                        "Parameters = StartIndex : 100, NbColumns : 2, NbEntries : 6");

                    try
                    {
                        baos = TrombinoscopeGenerator.generatePdfTrombinoscope(100,
                                2, 6, entries, attrs);
                        testPdfTromb(baos);
                    }
                    catch (ServiceException serex)
                    {
                        _test.displayResultSuccess("Error handled");
                    }
                    catch (Exception ex)
                    {
                        _test.displayResultFailure(ex.toString());
                    }

                    _test.displayMsg(TestUtils.NEXT +
                        "Parameters = StartIndex : 1, NbColumns : 2, NbEntries : -1");

                    try
                    {
                        baos = TrombinoscopeGenerator.generatePdfTrombinoscope(1,
                                2, -1, entries, attrs);
                        testPdfTromb(baos);
                    }
                    catch (ServiceException serex)
                    {
                        _test.displayResultSuccess("Error handled");
                    }
                    catch (Exception ex)
                    {
                        _test.displayResultFailure(ex.toString());
                    }

                    _test.displayMsg(TestUtils.NEXT +
                        "Parameters = StartIndex : 1, NbColumns : 2, NbEntries : 20");

                    try
                    {
                        baos = TrombinoscopeGenerator.generatePdfTrombinoscope(1,
                                2, 20, entries, attrs);
                        testPdfTromb2(baos);
                    }
                    catch (ServiceException serex)
                    {
                        _test.displayResultSuccess("Error handled");
                    }
                    catch (Exception ex)
                    {
                        _test.displayResultFailure(ex.toString());
                    }

                    _test.displayMsg(TestUtils.NEXT +
                        "Parameters = StartIndex : 1, NbColumns : 2, NbEntries : 0");

                    try
                    {
                        baos = TrombinoscopeGenerator.generatePdfTrombinoscope(1,
                                2, 0, entries, attrs);
                        testPdfTromb(baos);
                    }
                    catch (ServiceException serex)
                    {
                        _test.displayResultSuccess("Error handled");
                    }
                    catch (Exception ex)
                    {
                        _test.displayResultFailure(ex.toString());
                    }

                    _test.displayMsg(TestUtils.NEXT +
                        "Parameters = StartIndex : 1, NbColumns : 0, NbEntries : 6");

                    try
                    {
                        baos = TrombinoscopeGenerator.generatePdfTrombinoscope(1,
                                0, 6, entries, attrs);
                        testPdfTromb(baos);
                    }
                    catch (ServiceException serex)
                    {
                        _test.displayResultSuccess("Error handled");
                    }
                    catch (Exception ex)
                    {
                        _test.displayResultFailure(ex.toString());
                    }

                    _test.displayMsg(TestUtils.NEXT +
                        "Parameters = StartIndex : 1, NbColumns : -1, NbEntries : 6");

                    try
                    {
                        baos = TrombinoscopeGenerator.generatePdfTrombinoscope(1,
                                -1, 6, entries, attrs);
                        testPdfTromb(baos);
                    }
                    catch (ServiceException serex)
                    {
                        _test.displayResultSuccess("Error handled");
                    }
                    catch (Exception ex)
                    {
                        _test.displayResultFailure(ex.toString());
                    }

                    _test.displayMsg(TestUtils.NEXT +
                        "Parameters = StartIndex : 1, NbColumns : 10, NbEntries : 6");

                    try
                    {
                        baos = TrombinoscopeGenerator.generatePdfTrombinoscope(1,
                                10, 6, entries, attrs);
                        testPdfTromb3(baos);
                    }
                    catch (ServiceException serex)
                    {
                        _test.displayResultSuccess("Error handled");
                    }
                    catch (Exception ex)
                    {
                        _test.displayResultFailure(ex.toString());
                    }

                    _test.displayMsg(TestUtils.NEXT +
                        "Parameters = Attributes : null");

                    try
                    {
                        baos = TrombinoscopeGenerator.generatePdfTrombinoscope(1,
                                2, 6, entries, null);
                        testPdfTromb(baos);
                    }
                    catch (ServiceException serex)
                    {
                        _test.displayResultSuccess("Error handled");
                    }
                    catch (Exception ex)
                    {
                        _test.displayResultFailure(ex.toString());
                    }

                    _test.displayMsg(TestUtils.NEXT +
                        "Parameters = Entries : null");

                    try
                    {
                        baos = TrombinoscopeGenerator.generatePdfTrombinoscope(1,
                                2, 6, null, attrs);
                        testPdfTromb(baos);
                    }
                    catch (ServiceException serex)
                    {
                        _test.displayResultSuccess("Error handled");
                    }
                    catch (Exception ex)
                    {
                        _test.displayResultFailure(ex.toString());
                    }
                }
                else
                {
                    _test.displayResultFailure("No entries");
                }
            }
            else
            {
                _test.displayResultFailure("SearchResult = null");
            }
        }
        catch (Exception ex)
        {
            StringBuffer msg = new StringBuffer();
            msg.append("Exception : ");
            msg.append(TestUtils.NEXT);
            msg.append(ex.toString());
            _test.displayResultError(msg.toString());
        }

        _test.displayFooterMethod("testGeneratePdfTrombinoscopeError");
    }

    /**
     * Checks if the size of the generated PDF is equal to the reference PDF.
     *
     * @param name  Name of the reference PDF file.
     * @param baos  The generated PDF.
     */
    private static void testPdfTrombX(String name, ByteArrayOutputStream baos)
    {
        if (baos != null)
        {
            // allows to create the reference pdf file for the following tests.
            //_test.createFile(name, PDF_PATH, baos.toByteArray());
            //_test.displayMsg("Number of entries : " + entries.size());
            //_test.displayMsg("First entries : " + ((JBTop)entries.get(0)).getDn());
            // Gets the reference pdf file.
            byte[] refPdf = _test.readBytesFromFile(name, PDF_PATH);
            _test.displayMsg("Size of the generated PDF : " + baos.size());
            _test.displayMsg("Size of the reference PDF : " + refPdf.length);

            if (baos.size() == refPdf.length)
            {
                _test.displayResultSuccess(null);
            }
            else
            {
                _test.displayResultFailure(null);
            }
        }
        else
        {
            _test.displayResultFailure("No trombinoscope generated");
        }
    }

    /**
     * Checks if the size of the generated PDF is equal to the reference PDF.
     *
     * @param baos  The generated PDF.
     */
    private static void testPdfTromb(ByteArrayOutputStream baos)
    {
        testPdfTrombX(PDF_NAME, baos);
    }

    /**
     * Checks if the size of the generated PDF is equal to the reference PDF.
     *
     * @param baos  The generated PDF.
     */
    private static void testPdfTromb2(ByteArrayOutputStream baos)
    {
        testPdfTrombX(PDF_NAME2, baos);
    }

    /**
     * Checks if the size of the generated PDF is equal to the reference PDF.
     *
     * @param baos  The generated PDF.
     */
    private static void testPdfTromb3(ByteArrayOutputStream baos)
    {
        testPdfTrombX(PDF_NAME3, baos);
    }

    /**
     * Checks if the size of the generated image is equal to the reference image.
     *
     * @param startIndex  Starting index.
     * @param nbCols   Number of columns.
     * @param nbEntries  Number of entries.
     * @param entries  List of the entries.
     * @param attributes  List of the attributes.
     * @param imageType  Type of the image.
     */
    private static void testImageTromb(int startIndex, int nbCols,
        int nbEntries, List entries, ArrayList attributes, String imageType)
    {
        _test.displayMsg("Trombi Image type : " + imageType);

        List tromb = null;
        try
        {
            tromb = TrombinoscopeGenerator.generateTrombinoscope(startIndex,
                nbCols, nbEntries, entries, attributes, imageType);
        }
        catch (Exception ex)
        {
            _test.displayResultFailure(ex.toString());
        }

        if (tromb != null)
        {
            ByteArrayOutputStream baos = (ByteArrayOutputStream) tromb.get(0);

            // allows to create the reference image file for the following tests.
            //_test.createFile(IMAGE_NAME + imageType, IMAGE_PATH, baos.toByteArray());
            //_test.displayMsg("Number of entries : " + entries.size());
            //_test.displayMsg("First entries : " + ((JBTop)entries.get(0)).getDn());
            // Gets the reference image file.
            byte[] refImage = _test.readBytesFromFile(IMAGE_NAME + imageType,
                    IMAGE_PATH);
            _test.displayMsg("Size of the generated image : " + baos.size());
            _test.displayMsg("Size of the reference image : " +
                refImage.length);

            if (baos.size() == refImage.length)
            {
                _test.displayResultSuccess(null);
            }
            else
            {
                _test.displayResultFailure(null);
            }
        }
        else
        {
            _test.displayResultFailure("No trombinoscope generated");
        }
    }
}
